package com.education.platform.management.config;

import com.alibaba.fastjson.JSON;
import com.education.platform.common.redis.RedisUtils;
import com.education.platform.common.util.StringUtils;
import com.education.platform.common.web.ResponseBuilder;
import com.education.platform.common.web.ResponseCode;
import com.education.platform.common.web.ResponseEntity;
import com.education.platform.management.constants.RedisCacheConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 权限处理过滤器
 */
@Profile({"pro","test","dev"})
@Component
public class SecurityFilter implements Filter {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;

    @Autowired
    private RedisUtils redisUtils;

    private final String TOKEN="token";

    @Value("${token.expire}")
    private int tokenExpire;

    @Override
    public void init(FilterConfig filterConfig)   {
    }
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Headers", "Authentication,Origin, reqUid, Content-Type, Accept,token");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");

        //OPTIONS请求直接放行
        if(request.getMethod().equals(HttpMethod.OPTIONS.toString())){
            filterChain.doFilter(request,response);
            return;
        }
        //白名单请求直接放行
        PathMatcher pathMatcher = new AntPathMatcher();
        for (String path : ignoreUrlsConfig.getUrls()) {
            if(pathMatcher.match(path,request.getRequestURI())){
                filterChain.doFilter(request,response);
                return;
            }
        }
        //验证
        ResponseEntity responseEntity =  this.checkToken(request);

        //处理结果
        executeResult(responseEntity,request,response,filterChain);
        ThreadUser.removeUser();
    }

    /**
     * 获取token
     * @param request
     * @return
     */
    private String getToken(HttpServletRequest request){
        String token = null;
        if( request.getHeaders(TOKEN).hasMoreElements()){
            token = request.getHeaders(TOKEN).nextElement();
        }
        return token;
    }

    /**
     * 验证token
     * @param request
     * @return
     */
    private ResponseEntity checkToken(HttpServletRequest request){
        String token = getToken(request);
        if(StringUtils.isEmpty(token)){
            log.info("----无效请求！："+request.getRequestURI());
            return new ResponseBuilder()
                    .code(ResponseCode.VALIDATE_FAIL.getCode())
                    .message("无效请求！")
                    .build();
        }
        String tokenRedisKey = RedisCacheConstant.KEY_APP_TOKEN+token;
        String userJsonStr=redisUtils.getString(tokenRedisKey);
        if(StringUtils.isEmpty(userJsonStr)){
            log.info(ResponseCode.OVER_TIME.getDesc()+":"+request.getRequestURI());
            return new ResponseBuilder()
                    .code(ResponseCode.OVER_TIME.getCode())
                    .message(ResponseCode.OVER_TIME.getDesc())
                    .build();
        }
        ThreadUser.setUserJson(userJsonStr);
        ThreadUser.setUserTokenRdisKey(tokenRedisKey);
        redisUtils.expire(tokenRedisKey,tokenExpire);
        return new ResponseBuilder()
                .code(ResponseCode.SUCCESS.getCode())
                .message(ResponseCode.SUCCESS.getDesc())
                .build();
    }

    /**
     * 执行校验结果
     * @param responseEntity
     * @param req
     * @param resp
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    private void executeResult(ResponseEntity responseEntity, ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        if (ResponseCode.SUCCESS.getCode().equals(responseEntity.getCode())){
            chain.doFilter(req, resp);
        }else{
            HttpServletResponse httpResponse = (HttpServletResponse) resp;
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setContentType("application/json");
            String json = JSON.toJSONString(responseEntity);
            try (PrintWriter pw = httpResponse.getWriter()) {
                pw.write(json);
                pw.flush();
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }



}
